//
//  AMapViewFactory.m
//  flutter_plugin_gdmap
//
//  Created by Xiaoka on 2021/8/30.
//

#import "AMapViewFactory.h"
#import "MyConstant.h"
#import "FlutterPluginGdmapPlugin.h"
#import "MAMapView.h"
#import <AMapNaviKit/MAMapKit.h>
#import "MANaviRoute.h"
#import "CommonUtility.h"
#import "CustomAnnotationView.h"
#import "CustomPointAnnotation.h"
#import "AddressPointAnnotation.h"
#import "AddressAnnotationView.h"


@implementation AMapViewFactory {
    
}

- (NSObject <FlutterMessageCodec> *)createArgsCodec {
    return [FlutterStandardMessageCodec sharedInstance];
}

- (NSObject <FlutterPlatformView> *)createWithFrame:(CGRect)frame
                                     viewIdentifier:(int64_t)viewId
                                          arguments:(id _Nullable)args {
    
    AMapView *view = [[AMapView alloc] initWithFrame:frame
                                      viewIdentifier:viewId];
    return view;
}

@end

@implementation AMapView {
    CGRect _frame;
    int64_t _viewId;
    FlutterMethodChannel *_channel;
    MAMapView *_mapView;
    
    FlutterResult _result;
    AMapSearchAPI *_search;
    
    CLLocation * _currentLocation;//最新坐标位置
    NSMutableArray *_addressArr;//所有点信息
    
    MANaviRoute *_overlay;
    
    AMapGeoPoint *startPoint;
    AMapGeoPoint *endPoint;
    
    NSInteger num;//是否收缩地图到路径范围
    NSString *_selectNum;//选中的标号
}

- (instancetype)initWithFrame:(CGRect)frame
               viewIdentifier:(int64_t)viewId {
    self = [super init];
    if (self) {
        _frame = frame;
        _viewId = viewId;
        
        _mapView = [[MAMapView alloc] initWithFrame:_frame];
        [self setup];
    }
    return self;
}

- (UIView *)view {
    return _mapView;
}

- (void)setup {
    NSLog(@"~~~~~控件初始化");
    num=1;
    _selectNum =@"0";
    //region 初始化地图配置, 跟android一样, 不能在view方法里设置, 不然地图会卡住不动, android端是直接把AMapOptions赋值到MapView就可以了
    // 尽可能地统一android端的api了, ios这边的配置选项多很多, 后期再观察吧
    
    [AMapServices sharedServices].enableHTTPS = YES;
    
    ///地图类型
    _mapView.mapType = MAMapTypeStandard;
    ///缩放等级
    _mapView.zoomLevel = 17;
    ///显示实时交通状况
    _mapView.showTraffic=YES;
    ///如果您需要进入地图就显示定位小蓝点，则需要下面两行代码
    _mapView.showsUserLocation=YES;
    _mapView.userTrackingMode = MAUserTrackingModeFollow;
    
    ///自定义定位小蓝点
    MAUserLocationRepresentation *r = [[MAUserLocationRepresentation alloc] init];
    r.showsAccuracyRing = NO;///精度圈是否显示，默认YES
    r.showsHeadingIndicator = NO;///是否显示方向指示(MAUserTrackingModeFollowWithHeading模式开启)。默认为YES
    r.enablePulseAnnimation = NO;///内部蓝色圆点是否使用律动效果, 默认YES
    //    r.image = [UIImage imageNamed:@"common_icon_location_blue"]; ///定位图标, 与蓝色原点互斥 不能设置大小～先用默认的图标
    [_mapView updateUserLocationRepresentation:r];
    
    ///控件交互
    _mapView.showsCompass= NO; // 设置成NO表示关闭指南针；YES表示显示指南针
    _mapView.showsScale= NO;  //设置成NO表示不显示比例尺；YES表示显示比例尺
    
    _mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    
    _channel = [FlutterMethodChannel methodChannelWithName:[NSString stringWithFormat:@"%@%lld",
                                                            [AMAP_CHANNEL_NAME stringByAppendingString:@"/map"], _viewId]
                                           binaryMessenger:[FlutterPluginGdmapPlugin registrar].messenger];
    
    __weak __typeof__(self) weakSelf = self;
    [_channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
        self->_result = result;
        if (weakSelf) {
            [weakSelf handleMethodCall:call result:result];
        }
    }];
    
    // 搜索api回调设置
    _search = [[AMapSearchAPI alloc] init];
    _search.delegate = self;
}

- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
    
    // 设置delegate, 渲染overlay和annotation的时候需要
    _mapView.delegate = self;
    NSLog(@"~~~~~插件接收到通信Method:%@", call.method);
    //更改线路顺序
    if ([@"changeList" isEqualToString:call.method]) {
        num=1;
        ///清除所有的标注点和覆盖层
        [_mapView removeOverlays:_mapView.overlays];
        [_mapView removeAnnotations:_mapView.annotations];
        
        ///当前的位置数据
        if (_mapView.userLocation.location==nil) {
            ///地图控件内获取定位失败,获取flutter传过来的定位点
            NSData *locationData = [call.arguments[@"location"] dataUsingEncoding:NSUTF8StringEncoding];
            NSDictionary *locationDic = [NSJSONSerialization JSONObjectWithData:locationData
                                                                        options:NSJSONReadingMutableContainers
                                                                          error:nil];
            
            _currentLocation=[[CLLocation alloc] initWithLatitude:[[locationDic objectForKey:@"latitude"] doubleValue] longitude:[[locationDic objectForKey:@"longitude"] doubleValue]];
        }else{
            _currentLocation=_mapView.userLocation.location;
        }
        
        ///地址列表
        NSData *listData = [call.arguments[@"list"] dataUsingEncoding:NSUTF8StringEncoding];
        _addressArr = [NSJSONSerialization JSONObjectWithData:listData
                                                                      options:NSJSONReadingMutableContainers
                                                                        error:nil];
        _selectNum=@"0";
        ///所有经纬度点位的集合
        NSMutableArray *latLngsArr = [[NSMutableArray alloc]init];
        NSMutableArray *aMapGeoPointArr = [[NSMutableArray alloc]init];
        
        for (int i=0; i<_addressArr.count; i++) {
            NSLog(@"-> %@",_addressArr[i]);
            ///将点加入集合
            CLLocation *location=[[CLLocation alloc] initWithLatitude:[[_addressArr[i] objectForKey:@"latitude"] doubleValue] longitude:[[_addressArr[i] objectForKey:@"longitude"] doubleValue]];
            [latLngsArr addObject:location];
            
            AMapGeoPoint *aMapGeoPoint=[[AMapGeoPoint alloc]init];
            aMapGeoPoint.latitude=[[_addressArr[i] objectForKey:@"latitude"] doubleValue];
            aMapGeoPoint.longitude=[[_addressArr[i] objectForKey:@"longitude"] doubleValue];
            [aMapGeoPointArr addObject:aMapGeoPoint];
            
            CustomPointAnnotation *pointAnn = [[CustomPointAnnotation alloc] init];
            pointAnn.coordinate = location.coordinate;
            pointAnn.title = [NSString stringWithFormat:@"%@", [_addressArr[i] objectForKey:@"numSort"]];
            pointAnn.num = [[_addressArr[i] objectForKey:@"numSort"] integerValue];
            pointAnn.ticketNumber = [[_addressArr[i] objectForKey:@"ticketNumber"] integerValue];
            pointAnn.phone = [NSString stringWithFormat:@"%@", [_addressArr[i] objectForKey:@"phone"]];
            [_mapView addAnnotation:pointAnn];
        }
        
        ///规划路径
        AMapDrivingRouteSearchRequest *navi = [[AMapDrivingRouteSearchRequest alloc] init];
        navi.requireExtension = NO;
        navi.strategy = 5;
        /* 出发点. */
        navi.origin = [AMapGeoPoint locationWithLatitude:_currentLocation.coordinate.latitude
                                               longitude:_currentLocation.coordinate.longitude];
        
        CLLocation *endLocation= [latLngsArr lastObject];
        /* 目的地. */
        navi.destination = [AMapGeoPoint locationWithLatitude:endLocation.coordinate.latitude
                                                    longitude:endLocation.coordinate.longitude];
        
        startPoint=navi.origin;
        endPoint=navi.destination;
        /* 途经点. */
        navi.waypoints=aMapGeoPointArr;
        [_search AMapDrivingRouteSearch:navi];
        
        result(@"设置成功");
    }else if ([@"checkPoint" isEqualToString:call.method]) {
        num=0;
        ///清除所有的标注点和覆盖层
        [_mapView removeOverlays:_mapView.overlays];
        [_mapView removeAnnotations:_mapView.annotations];
        
        ///当前的位置数据
        if (_mapView.userLocation.location==nil) {
            ///地图控件内获取定位失败,获取flutter传过来的定位点
            NSData *locationData = [call.arguments[@"location"] dataUsingEncoding:NSUTF8StringEncoding];
            NSDictionary *locationDic = [NSJSONSerialization JSONObjectWithData:locationData
                                                                        options:NSJSONReadingMutableContainers
                                                                          error:nil];
            
            _currentLocation=[[CLLocation alloc] initWithLatitude:[[locationDic objectForKey:@"latitude"] doubleValue] longitude:[[locationDic objectForKey:@"longitude"] doubleValue]];
        }else{
            _currentLocation=_mapView.userLocation.location;
        }
        
        ///地址列表
        NSData *listData = [call.arguments[@"list"] dataUsingEncoding:NSUTF8StringEncoding];
        _addressArr = [NSJSONSerialization JSONObjectWithData:listData
                                                                      options:NSJSONReadingMutableContainers
                                                                        error:nil];
        ///查看固定点
        NSData *pointData = [call.arguments[@"latLng"] dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *pointDataDic = [NSJSONSerialization JSONObjectWithData:pointData
                                                                    options:NSJSONReadingMutableContainers
                                                                      error:nil];
        _selectNum=[NSString stringWithFormat:@"%@", [pointDataDic objectForKey:@"numSort"]];
        ///所有经纬度点位的集合
        NSMutableArray *latLngsArr = [[NSMutableArray alloc]init];
        NSMutableArray *aMapGeoPointArr = [[NSMutableArray alloc]init];
        
        for (int i=0; i<_addressArr.count; i++) {
            
            CLLocation *location=[[CLLocation alloc] initWithLatitude:[[_addressArr[i] objectForKey:@"latitude"] doubleValue] longitude:[[_addressArr[i] objectForKey:@"longitude"] doubleValue]];
            [latLngsArr addObject:location];
            
            AMapGeoPoint *aMapGeoPoint=[[AMapGeoPoint alloc]init];
            aMapGeoPoint.latitude=[[_addressArr[i] objectForKey:@"latitude"] doubleValue];
            aMapGeoPoint.longitude=[[_addressArr[i] objectForKey:@"longitude"] doubleValue];
            [aMapGeoPointArr addObject:aMapGeoPoint];
            
            ///添加数字Marker
            if([[_addressArr[i] objectForKey:@"numSort"] integerValue] != [[pointDataDic objectForKey:@"numSort"] integerValue]){
                CustomPointAnnotation *pointAnn = [[CustomPointAnnotation alloc] init];
                pointAnn.coordinate = location.coordinate;
                pointAnn.title = [NSString stringWithFormat:@"%@", [_addressArr[i] objectForKey:@"numSort"]];
                pointAnn.num = [[_addressArr[i] objectForKey:@"numSort"] integerValue];
                pointAnn.ticketNumber = [[_addressArr[i] objectForKey:@"ticketNumber"] integerValue];
                pointAnn.phone = [NSString stringWithFormat:@"%@", [_addressArr[i] objectForKey:@"phone"]];
                [_mapView addAnnotation:pointAnn];
            }
        }
        
        ///规划路径
        AMapDrivingRouteSearchRequest *navi = [[AMapDrivingRouteSearchRequest alloc] init];
        navi.requireExtension = NO;
        navi.strategy = 5;
        /* 出发点. */
        navi.origin = [AMapGeoPoint locationWithLatitude:_currentLocation.coordinate.latitude
                                               longitude:_currentLocation.coordinate.longitude];
        
        CLLocation *endLocation= [latLngsArr lastObject];
        /* 目的地. */
        navi.destination = [AMapGeoPoint locationWithLatitude:endLocation.coordinate.latitude
                                                    longitude:endLocation.coordinate.longitude];
        
        startPoint=navi.origin;
        endPoint=navi.destination;
        /* 途经点. */
        navi.waypoints=aMapGeoPointArr;
        [_search AMapDrivingRouteSearch:navi];
        
        ///添加地址Marker
        CLLocation *newLocation=[[CLLocation alloc] initWithLatitude:[[pointDataDic objectForKey:@"latitude"] doubleValue] longitude:[[pointDataDic objectForKey:@"longitude"] doubleValue]];
        AddressPointAnnotation *addPointAnn = [[AddressPointAnnotation alloc] init];
        addPointAnn.coordinate = newLocation.coordinate;
        addPointAnn.title = [NSString stringWithFormat:@"%@", [pointDataDic objectForKey:@"numSort"]];
        addPointAnn.num = [[pointDataDic objectForKey:@"numSort"] integerValue];
        addPointAnn.ticketNumber = [[pointDataDic objectForKey:@"ticketNumber"] integerValue];
        addPointAnn.phone = [NSString stringWithFormat:@"%@", [pointDataDic objectForKey:@"phone"]];
        addPointAnn.address = [NSString stringWithFormat:@"%@", [pointDataDic objectForKey:@"address"]];
        [_mapView addAnnotation:addPointAnn];
        
        CLLocationCoordinate2D coord = CLLocationCoordinate2DMake([[pointDataDic objectForKey:@"latitude"] doubleValue],[[pointDataDic objectForKey:@"longitude"] doubleValue]);
        [_mapView setCenterCoordinate:coord animated:YES];
        result(@"查看固定点成功");
    }else if ([@"setZoomTo" isEqualToString:call.method]) {
        //设置地图的缩放比例
        NSInteger num = [[call.arguments objectForKey:@"num"] integerValue];
        [_mapView setZoomLevel:num animated:YES];
        result(@"设置地图的缩放比例成功");
    }else {
        result(FlutterMethodNotImplemented);
    }
}

#pragma AMapSearchDelegate
/// 路径规划搜索回调.
- (void)onRouteSearchDone:(AMapRouteSearchBaseRequest *)request response:(AMapRouteSearchResponse *)response {
    NSLog(@"路线规划成功:");
    if (response.route == nil){
        return;
    }
    if (response.count > 0){
        // 添加中间的路径
        AMapPath *path = response.route.paths[0];
        _overlay = [MANaviRoute naviRouteForPath:path
                                    withNaviType:MANaviAnnotationTypeDrive
                                     showTraffic:YES
                                      startPoint:startPoint
                                        endPoint:endPoint];
        [_overlay addToMapView:_mapView];
    
        if (num==1) {
            // 收缩地图到路径范围
            [_mapView setVisibleMapRect:[CommonUtility mapRectForOverlays:_overlay.routePolylines]
                            edgePadding:UIEdgeInsetsMake(20, 20, 20, 20)
                               animated:YES];
        }
    }
}

/// 路线规划失败回调
- (void)AMapSearchRequest:(id)request didFailWithError:(NSError *)error {
    NSLog(@"路线规划失败: %@", error);
}

#pragma MAMapViewDelegate
/// 渲染overlay回调
- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id <MAOverlay>)overlay {
    NSLog(@"渲染overlay回调:");
    if ([overlay isKindOfClass:[MAMultiPolyline class]]) {
        MAMultiColoredPolylineRenderer *polylineRenderer = [[MAMultiColoredPolylineRenderer alloc] initWithMultiPolyline:overlay];
        polylineRenderer.lineWidth = 6;
        polylineRenderer.strokeColors = [_overlay.multiPolylineColors copy];
        return polylineRenderer;
    }
    else if ([overlay isMemberOfClass:[LineDashPolyline class]]) {
        LineDashPolyline *polyline = (LineDashPolyline *)overlay;
        MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:polyline];
        polylineRenderer.lineWidth = 6;
        polylineRenderer.lineDashType = kMALineDashTypeSquare;
        return polylineRenderer;
    }
    return nil;
}

/// 渲染annotation, 就是Android中的marker
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation {
    NSLog(@"渲染annotation回调:");
    if ([annotation isKindOfClass:[CustomPointAnnotation class]]) {
        NSLog(@"序号marker");
        static NSString *reuseIndetifier = @"annotationReusePopUp";
        CustomAnnotationView *annotationView = (CustomAnnotationView *)[_mapView dequeueReusableAnnotationViewWithIdentifier:reuseIndetifier];
        if (annotationView == nil)
        {
            annotationView = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseIndetifier];
        }
        
        annotationView.annotation = annotation;
        annotationView.canShowCallout = NO;
        annotationView.draggable = YES;
//        annotationView.calloutOffset = CGPointMake(0, 18);
        CustomPointAnnotation *pointAnn = (CustomPointAnnotation *)annotation;
        annotationView.numSort=[NSString stringWithFormat:@"%ld", pointAnn.num];
        [annotationView setSelected:NO animated:YES];
        
        return annotationView;
    }else if ([annotation isKindOfClass:[AddressPointAnnotation class]]) {
        NSLog(@"地址marker");
        static NSString *reuseIndetifier = @"addressAnnotationReusePopUp";
        AddressAnnotationView *annotationView = (AddressAnnotationView *)[_mapView dequeueReusableAnnotationViewWithIdentifier:reuseIndetifier];
        if (annotationView == nil)
        {
            annotationView = [[AddressAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseIndetifier];
        }
        
        annotationView.annotation = annotation;
        annotationView.canShowCallout = NO;
        annotationView.draggable = YES;
//        annotationView.calloutOffset = CGPointMake(0, 18);
        AddressPointAnnotation *pointAnn = (AddressPointAnnotation *)annotation;
        annotationView.numSort=[NSString stringWithFormat:@"%ld", pointAnn.num];
        [annotationView setPhone:pointAnn.phone setTicketNumber:pointAnn.ticketNumber];
        [annotationView setAddress:pointAnn.address];
        [annotationView setSelected:YES animated:YES];
        
        return annotationView;
    }
    
    return nil;
}

///当选中一个annotation view时，调用此接口. 注意如果已经是选中状态，再次点击不会触发此回调
- (void)mapView:(MAMapView *)mapView didSelectAnnotationView:(MAAnnotationView *)view{
    NSLog(@"点击的标注点: %@", view.annotation.title);
    if(![_selectNum isEqualToString:@"0"] && [_selectNum isEqualToString: view.annotation.title]){
        NSLog(@"标注点已是选中状态: %@", view.annotation.title);
        return ;
    }
    _selectNum=view.annotation.title;
    //通知flutter
    [_channel invokeMethod:@"clickMarker" arguments:view.annotation.title];
    
    ///清除所有的标注点
    [_mapView removeAnnotations:_mapView.annotations];
    
    CLLocationCoordinate2D coord;
    for (int i=0; i<_addressArr.count; i++) {
        ///添加数字Marker
        if(![[[_addressArr[i] objectForKey:@"numSort"] stringValue] isEqualToString:_selectNum]){
            CLLocation *location=[[CLLocation alloc] initWithLatitude:[[_addressArr[i] objectForKey:@"latitude"] doubleValue]   longitude:[[_addressArr[i] objectForKey:@"longitude"] doubleValue]];
        
            CustomPointAnnotation *pointAnn = [[CustomPointAnnotation alloc] init];
            pointAnn.coordinate = location.coordinate;
            pointAnn.num = [[_addressArr[i] objectForKey:@"numSort"] integerValue];
            pointAnn.title = [NSString stringWithFormat:@"%@", [_addressArr[i] objectForKey:@"numSort"]];
            pointAnn.ticketNumber = [[_addressArr[i] objectForKey:@"ticketNumber"] integerValue];
            pointAnn.phone = [NSString stringWithFormat:@"%@", [_addressArr[i] objectForKey:@"phone"]];
            [_mapView addAnnotation:pointAnn];
        }else{
            ///添加地址Marker
            CLLocation *newLocation=[[CLLocation alloc] initWithLatitude:[[_addressArr[i] objectForKey:@"latitude"] doubleValue]    longitude:[[_addressArr[i] objectForKey:@"longitude"] doubleValue]];
            AddressPointAnnotation *addPointAnn = [[AddressPointAnnotation alloc] init];
            addPointAnn.coordinate = newLocation.coordinate;
            addPointAnn.num = [[_addressArr[i] objectForKey:@"numSort"] integerValue];
            addPointAnn.title = [NSString stringWithFormat:@"%@", [_addressArr[i] objectForKey:@"numSort"]];
            addPointAnn.ticketNumber = [[_addressArr[i] objectForKey:@"ticketNumber"] integerValue];
            addPointAnn.phone = [NSString stringWithFormat:@"%@", [_addressArr[i] objectForKey:@"phone"]];
            addPointAnn.address = [NSString stringWithFormat:@"%@", [_addressArr[i] objectForKey:@"address"]];
            [_mapView addAnnotation:addPointAnn];
            coord = CLLocationCoordinate2DMake([[_addressArr[i] objectForKey:@"latitude"] doubleValue],[[_addressArr[i]  objectForKey:@"longitude"] doubleValue]);
            }
    }
    [_mapView setCenterCoordinate:coord animated:YES];
    [_mapView setZoomLevel:13 animated:YES];
}

@end
